using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace GraphMyCode.Controls
{
	public class GraphNodeDescriptor : GraphItemDescriptor
	{
		public static readonly DependencyProperty CentralPointProperty =
			DependencyProperty.Register("CentralPoint", typeof(Point), typeof(GraphNodeDescriptor), null);

		private readonly List<GraphItem> inEdges = new List<GraphItem>();
		private readonly List<GraphItem> outEdges = new List<GraphItem>();
		private Point absoluteCentralPoint;
		private Size canvasSize;

		public Point CentralPoint
		{
			get { return (Point)GetValue(CentralPointProperty); }
			set { SetValue(CentralPointProperty, value); }
		}

		internal override double Left
		{
			//NOTE: Round - used for pixel snapping.
			get { return (int)Math.Round(AbsoluteCentralPoint.X - Shape.Bounds.Width / 2); }
		}

		internal override double Top
		{
			//NOTE: Round - used for pixel snapping.
			get { return (int)Math.Round(AbsoluteCentralPoint.Y - Shape.Bounds.Height / 2); }
		}

		internal override int ZIndex
		{
			get { return Item.IsSelected ? 3 : 2; }
		}

		public List<GraphItem> InEdges
		{
			get { return inEdges; }
		}

		public List<GraphItem> OutEdges
		{
			get { return outEdges; }
		}

		public Point AbsoluteCentralPoint
		{
			get { return absoluteCentralPoint; }
			set
			{
				if (absoluteCentralPoint != value)
				{
					absoluteCentralPoint = value;

					foreach (GraphItem item in InEdges.Union(OutEdges))
					{
						item.ItemDescriptor.UpdatePosition();
					}
					UpdatePosition();

					CentralPoint = GetCentralPoint();
				}
			}
		}

		public Size CanvasSize
		{
			get { return canvasSize; }
			set
			{
				if (canvasSize != value)
				{
					canvasSize = value;
					AbsoluteCentralPoint = GetAbsoluteCentralPoint();
				}
			}
		}

		internal Path GetVisualPath()
		{
			var path = new Path
			           	{
			           		Fill = new SolidColorBrush(Colors.Black),
			           		Data = Shape
			           	};
			return path;
		}

		internal void Move(double offsetX, double offsetY)
		{
			AbsoluteCentralPoint = new Point(AbsoluteCentralPoint.X + offsetX, AbsoluteCentralPoint.Y + offsetY);
		}

		internal void Move(Point p)
		{
			AbsoluteCentralPoint = p;
		}

		private Point GetCentralPoint()
		{
			if (canvasSize.Width != 0 && canvasSize.Height != 0)
				return new Point(AbsoluteCentralPoint.X / canvasSize.Width, AbsoluteCentralPoint.Y / canvasSize.Height);

			//throw new ArithmeticException("Canvas size is zero!");
			return new Point();
		}

		private Point GetAbsoluteCentralPoint()
		{
			return new Point(CentralPoint.X * canvasSize.Width, CentralPoint.Y * canvasSize.Height);
		}
	}
}